package capstone.tagit;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;


public class TagItMapActivity extends MapActivity {
	//Variables 
	TagItMapActivity parent;
	String ACTNAME = "TagIt!";
	MapView mapView;	//Map handler
	LocationManager locationManager; //Location manager
	LocationListener locationListener; //location listener
	MapController mapControl;	//Map control
	TagsList tagsOnScreen;
	MyLocationOverlay myLocationOverlay; 
	List<Overlay> mapOverlays;
	ArrayList<TagType> tagTypes = new ArrayList<TagType>();
	ArrayList<String> typeNames = new ArrayList<String>();
	ArrayList<String> attributes;
	ArrayList<String> tagBuffer;
	LinkedList<Tag> tagsForServer;
	
	//Radius check
	int radius = 50;
	//	OverlayItem overlayitem;
	GeoPoint currentLocationPoint;
	SharedPreferences menuSettings;
	SharedPreferences.Editor prefEditor;
	//	int checkBoxState;
	TagType currentType;
	String TagFileName = "tagfile";
	String saveFileName = "savefile";
	SimpleDateFormat dateFormat;
	AppClient connection;
	String serverAddress;
	int serverPort;
	Resources resource;
	//server communication
	@Override
	//Method is called on start-up of application
	public void onCreate(Bundle savedInstanceState) {
		Log.v("onCreate", "line 83");
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		parent = this;
		resource = getResources();
		locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
		locationListener = new myLocationListener();
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000,10,locationListener);
		//Button stuff
		Button tagButton = (Button)findViewById(R.id.Button4);
		tagButton.setOnClickListener(tagListener);
		Button menu = (Button) findViewById(R.id.Button1);
		menu.setOnClickListener(menuListener);
		Button refreshButton = (Button)findViewById(R.id.refreshButton);
		refreshButton.setOnClickListener(refreshListener);
		//
		menuSettings = getSharedPreferences("MenuPref", MODE_PRIVATE);
		prefEditor = menuSettings.edit();
		prefEditor.putBoolean("GPS_STATUS",true);
		prefEditor.commit();
		attributes = new ArrayList<String>();
		dateFormat = new SimpleDateFormat(resource.getString(R.string.Date));
		tagsForServer = new LinkedList<Tag>();
		getTagTypes();
		getAttributesFromFile();
		initMap();
		serverAddress = resource.getString(R.string.serveraddress);//grab server address from server.xml 
		//maybe move all that to one settings file
		serverPort = resource.getInteger(R.integer.port);
		connection = new AppClient(serverAddress,serverPort);
		//getTagsFromServer();
		Log.v(ACTNAME,"Done getting tags from server");
		getTagsFromFile();  
		//remote_getTags(currentLocationPoint.getLongitudeE6(), currentLocationPoint.getLatitudeE6(), 500);
		//remote_getTags(-122048095, 37422006, 5000);
		//remote_setTags();
		//Log.v("check format",pendingTags.get(0).getInfoString(dateFormat));
		
	}
	//config
	private void getTagTypes(){
		String[] typesFromFile = resource.getStringArray(R.array.type_array);
		TypedArray pictures = resource.obtainTypedArray(R.array.pic_array);
		for (int i = 0; i < typesFromFile.length; i++){
			String name = typesFromFile[i];
//			Log.v(ACTNAME,name + " " + Integer.toString(pictures[i]));
			Drawable marker = pictures.getDrawable(i);
			int width = marker.getIntrinsicWidth();
			int height = marker.getIntrinsicHeight();
			marker.setBounds(-width/2, -height, width/2, 0);
			tagTypes.add(new TagType(name, marker));
			typeNames.add(name);
			prefEditor.putBoolean(name,true);			
		}
		prefEditor.putInt("COLOR_CHOICE",0);
		currentType = tagTypes.get(0);
		//		}catch(IOException e){}
	}
	//config
	private void getAttributesFromFile(){
		String[] attribute_names = resource.getStringArray(R.array.attribute_names);
		for (String attribute : attribute_names){
			attributes.add(attribute);
		}
	}
	
	private void getTagsFromFile(){
		InputStream tagsFile = null;
		try{
			tagsFile = openFileInput(TagFileName);
		}catch(FileNotFoundException e){
			return;
		}
		BufferedReader readTags = new BufferedReader(new InputStreamReader(tagsFile));
		try{
			String tagLine;
			while((tagLine = readTags.readLine()) != null){
				
				Tag overlayItem = Tag.parseStringToTag(tagLine,tagTypes,attributes,dateFormat);
				if (overlayItem != null){
					addOverlayItem(overlayItem);
				}
			}
		}catch(Exception e){}
	}

	//change the next two function names whenever
	//remote_request queries server with a central location and radius to search in database
	//php script needs to compute radius
	//longitude(uD), latitude(uD), radius(miles)
	private void remote_getTags(final int longitude, final int latitude, final double radius){
		(new Thread(){
			public void run(){ //start connection
				try{  
					ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>(); //necessary for Post entity
					nameValuePair.add(new BasicNameValuePair("longitude",Integer.toString(longitude)));
					nameValuePair.add(new BasicNameValuePair("latitude", Integer.toString(latitude)));
					nameValuePair.add(new BasicNameValuePair("radius",Double.toString(radius)));
					tagBuffer = new ArrayList<String>();
					HttpClient httpclient = new DefaultHttpClient();
					HttpPost httppost = new HttpPost("http://"+serverAddress+"/getTags.php");
					httppost.setEntity(new UrlEncodedFormEntity(nameValuePair));
					HttpResponse response = httpclient.execute(httppost);
					BufferedReader input = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
					String line = "";
					Log.v("Connection","Printing out valid information");
					while((line = input.readLine())!= null){//Read in all the stuff
						Log.v("Output Line", line.toString());
						if(line.length()>0)tagBuffer.add(line.toString());
					} 
					input.close();
					if(!tagBuffer.isEmpty()){
						Log.v("outputting tag buffer", tagBuffer.toString());
						for(String tempTag : tagBuffer){
							final Tag temp = Tag.parseStringToTag(tempTag, tagTypes, attributes,dateFormat);
							if(temp != null){
								Runnable addTag = new Thread(){
									Tag item = temp;
									public void run(){
										if(addOverlayItem(item)){
											Log.v("line 240", "adding");
											writeToFile(item);
										}
									}
								};
								parent.runOnUiThread(addTag);
							}
						}
					}
					//add a replace to delimit stringbuffer
					}catch(Exception e){ 
						Log.e("catch",e.toString()); 
					}

		}
		}).start();
	}
	private void remote_setTags(){
		(new Thread(){ 
			public void run(){
				try{
					//for(Tag temp: tags){
						ArrayList<NameValuePair> nameValuePair = new ArrayList<NameValuePair>();
						//test\
						//encode tags into nameValuePairs

						//test tag 
						int i = 0;
						if(!tagsForServer.isEmpty()){
						for(Tag temp : tagsForServer){		
							//use this as a basis for parsing a tag to string
							
							nameValuePair.add(new BasicNameValuePair(Integer.toString(i), temp.getInfoString(dateFormat)));
							i++;
						}
						//clear pendingTags
						tagsForServer = new LinkedList<Tag>();
						//connecting to server
						HttpClient httpclient = new DefaultHttpClient();
						HttpPost httppost = new HttpPost("http://"+serverAddress+"/setTags.php");
						httppost.setEntity(new UrlEncodedFormEntity(nameValuePair));
						HttpResponse response = httpclient.execute(httppost);
						BufferedReader input = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
						String line = ""; 
						while((line = input.readLine())!= null){//Read in all the stuff
							Log.v("Output Line", line.toString());
						}
						input.close(); 
					}
				}catch(Exception e){
					Log.e("catch",e.toString());
				}
			}
		
		}).start();
	}
	private OnClickListener tagListener = new OnClickListener(){
		public void onClick(View view) {
			Intent myIntent = new Intent(view.getContext(), TaggingActivity.class);
			myIntent.putStringArrayListExtra("attributes", attributes);
			startActivityForResult(myIntent, 1);
		} 
	};
	private OnClickListener menuListener = new OnClickListener(){
		public void onClick(View view) {
			Intent myIntent = new Intent(view.getContext(), MenuActivity.class);
			myIntent.putStringArrayListExtra("tagtypes",typeNames);
			startActivityForResult(myIntent, 0);
		}
	};
	private OnClickListener refreshListener = new OnClickListener(){
		public void onClick(View view){
			//getTagsFromServer();
			int longi = currentLocationPoint.getLongitudeE6();
			int lati = currentLocationPoint.getLatitudeE6();
			//remote_getTags(longi, lati,radius);
			remote_setTags();	
		}
	};
	private void writeToFile(Tag tag){
		try{
			FileOutputStream writer = openFileOutput(TagFileName,Context.MODE_APPEND);
			writer.write(tag.getInfoString(dateFormat).getBytes());
			writer.close();		
		}catch(Exception e){
			Log.v(ACTNAME,"Exception caught in writing to tagFile");
		} //the method is supposed to create the file, there *should* be no exception
	}
	protected void onResume(){
		super.onResume();
		myLocationOverlay.enableMyLocation();
	}
	protected void onPause(){
		super.onPause();
		myLocationOverlay.disableMyLocation();
		myLocationOverlay.disableCompass();
	}
	protected void onActivityResult(int requestCode, int resultCode,
			Intent data) {
		// 		int filterSeed = randGen.nextInt()+1;
		if (resultCode == RESULT_OK && requestCode == 0) {	
			if (!menuSettings.getBoolean("GPS_STATUS",true)){
				locationManager.removeUpdates(locationListener);
			}else{
				locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
				myLocationOverlay.enableMyLocation();
				myLocationOverlay.enableCompass();
			}

			for (TagType type : tagTypes){
				Log.v(ACTNAME,Boolean.toString(menuSettings.getBoolean(type.getName(),true)));
				if (menuSettings.getBoolean(type.getName(),true)){
					tagsOnScreen.filterInType(type);
				}
				else{
					tagsOnScreen.filterOutType(type);
				}
			}

			//until Menu_Activity is fixed
			int tagTypeNum = menuSettings.getInt("COLOR_CHOICE",0);
			currentType = tagTypes.get(tagTypeNum);
			tagsOnScreen.filterList();
			mapView.invalidate();
		}
		if (requestCode == 1){
			if (resultCode == 0){ //tag submitted
				String title = data.getStringExtra("title");
				String description = data.getStringExtra("description");
				final Tag tag = new Tag(currentLocationPoint,title,description);
				tag.setType(currentType);
				tag.setMarker(currentType.getMarker());
				String date = dateFormat.format(new Date());
				try {
					tag.setDate(dateFormat.parse(date));
					
				} catch (ParseException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				for (String attribute : attributes){
					tag.addAttribute(attribute, data.getStringExtra(attribute));
				}
				if(addOverlayItem(tag)){
					writeToFile(tag);
				} 
				
				tagsForServer.add(tag);
				Log.v("Adding stuff to tagsForServer", " Current Number of Tags: "+Integer.toString(tagsForServer.size()));
	/*			(new Thread(){
					public void run(){ 
						try{
							connection.connect(serverAddress,serverPort);
							connection.writeToServer(tag);
							connection.closeConnection();
						}catch(Exception e){}
					}
				}).start();*/
			}
		}
	}
	private boolean addOverlayItem(Tag item){
		boolean rVal = tagsOnScreen.addOverlay(item);
		//mapOverlays.add(mapItem);
		mapView.invalidate(); 
		return rVal;
	}
	@Override
	protected boolean isRouteDisplayed() {
		// TODO Auto-generated method stub
		return false;
	}
	//
	private void initMap(){
		mapView = (MapView) findViewById(R.id.GMap);	
		mapControl = mapView.getController();
		mapView.setBuiltInZoomControls(true);
		mapControl.setZoom(15);
		tagsOnScreen = new TagsList(currentType.getMarker(), this);
		mapOverlays = mapView.getOverlays();
		mapOverlays.add(tagsOnScreen);
		myLocationOverlay = new MyLocationOverlay(this, mapView);
		mapView.getOverlays().add(myLocationOverlay);
		mapView.invalidate();
	}
	private class myLocationListener implements LocationListener 
	{
		@Override
		public void onLocationChanged(Location loc) {
			if (loc != null) {
				//Geopoints in microdegrees latitude or longitude times 10^6
				currentLocationPoint = new GeoPoint((int)(loc.getLatitude() * 1000000.0), (int)(loc.getLongitude()*1000000.0));
				Toast.makeText(getBaseContext(), 
						"Location changed : Latitude: " + loc.getLatitude() + 
						" Longitude: " + loc.getLongitude(), 
						Toast.LENGTH_SHORT).show();
				//mapControl.setCenter(currentLocationPoint); //should be removed for actual app use.  Maybe?
			}
		}
		@Override
		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
		}

		@Override
		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
		}
	}    

}